#include "select.h"
#include "tcp_socket.h"
#include <iostream>

using std::cout;
using std::endl;

select_engine::select_engine():maxi(0), nready(0)
{
	FD_ZERO(&rset);
	FD_ZERO(&allset);

	for (int i = 0; i < 10; ++i)
	{
		clientfd[i].fd = -1;
		memset(clientfd[i].id, 0, 12);
	}

	tcp = new tcp_socket("192.168.1.240", 5566);
	sockfd = tcp->init_socket();
	fd_add(sockfd);

	maxfd = 0;
	if (sockfd > maxfd)
		maxfd = sockfd;
}

select_engine::~select_engine()
{
	if (tcp)
	{
		delete tcp;
		tcp = NULL;
	}
}

bool select_engine::isconnect()
{
	int fd = -1;
	int i = 0;

	if (FD_ISSET(sockfd, &rset))
	{
		fd = tcp->accept();

		if (fd > maxfd)
			maxfd = fd;

		for (i = 0; i < 10; ++i)
		{
			if (clientfd[i].fd  < 0)
			{
				clientfd[i].fd = fd;
				break;
			}
		}

		fd_add(fd);

		if (i > maxi)
			maxi = i;

		nready -= 1;
	}

	return true;
}

bool select_engine::isread()
{
	int i = 0;
	int fd = -1;

	for (i = 0; i <= maxi; ++i)
	{
		if ((fd = clientfd[i].fd) <= 0)
		{
			continue;
		}

		if (FD_ISSET(fd, &rset))
		{
			CHAT_MSG msg;
			int len = sizeof(msg);
			memset((void *)&msg, 0, len);

			int ret = 0;
			ret = tcp_recv(fd, (void *)&msg, len, 0);
			if (ret <= 0)
			{
				close(fd);
				fd_del(fd);
			}
			else
			{
				if (msg.type == LOGIN)
				{
					printf("[%s] login.\n", msg.src_id);
					strcpy(clientfd[i].id, msg.src_id);
				}
				else
				{
					for (i = 0; i < 10; ++i)
					{
						if (strcmp(clientfd[i].id, msg.dst_id) == 0)
						{
							tcp_send(clientfd[i].fd, (void *)&msg, ret, 0);
							break;
						}
					}

					if (i == 10)
					{
						memset(msg.src_id, 0, 12);
						strcpy(msg.src_id, "system");
						memset(msg.buf, 0, 512);
						strcpy(msg.buf, "you friend not online!\n");
						tcp_send(fd, (void *)&msg, len, 0);
					}
				}
			}

			if (--nready <= 0)
				break;
		}
	}

	return true;
}

bool select_engine::fd_loop()
{
	while (1)
	{
		rset = allset;

		nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
		cout << "nready: " << nready << endl;
		isconnect();

		if (nready <= 0)
			continue;

		isread();
	}
}

int select_engine::tcp_recv(int fd, void *buf, int len, int flag)
{
	return (recv(fd, buf, len, flag));
}

int select_engine::tcp_send(int fd, const void *buf, int len, int flag)
{
	return (send(fd, buf, len, flag));
}

bool select_engine::fd_add(int fd)
{
	FD_SET(fd, &allset);

	return true;
}

bool select_engine::fd_del(int fd)
{
	FD_CLR(fd, &allset);

	return true;
}

